<template>
	<div class="app-container">
		<div class="search-container">
			<el-form ref="queryFormRef" :inline="true" :model="queryParams">
				<el-form-item label="关键字" prop="keywords">
					<el-input
						v-model="queryParams.keywords"
						clearable
						placeholder="角色名称"
						@keyup.enter="handleQuery"
					/>
				</el-form-item>

				<el-form-item>
					<el-button type="primary" @click="handleQuery"
					>
						<i-ep-search/>
						搜索
					</el-button
					>
					<el-button @click="handleResetQuery">
						<i-ep-refresh/>
						重置
					</el-button>
				</el-form-item>
			</el-form>
		</div>

		<el-card class="table-container" shadow="never">
			<template #header>
				<el-button type="success" @click="handleOpenDialog()"
				>
					<i-ep-plus/>
					新增
				</el-button
				>
				<el-button
					:disabled="ids.length === 0"
					type="danger"
					@click="handleDelete()"
				>
					<i-ep-delete/>
					删除
				</el-button
				>
			</template>

			<el-table
				ref="dataTableRef"
				v-loading="loading"
				:data="roleList"
				border
				highlight-current-row
				@selection-change="handleSelectionChange"
			>
				<el-table-column align="center" type="selection" width="55"/>
				<el-table-column label="角色名称" min-width="100" prop="name"/>
				<el-table-column label="角色编码" prop="code" width="150"/>

				<el-table-column align="center" label="状态" width="100">
					<template #default="scope">
						<el-tag v-if="scope.row.status === 1" type="success">正常</el-tag>
						<el-tag v-else type="info">禁用</el-tag>
					</template>
				</el-table-column>

				<el-table-column align="center" label="排序" prop="sort" width="80"/>

				<el-table-column fixed="right" label="操作" width="220">
					<template #default="scope">
						<el-button
							link
							size="small"
							type="primary"
							@click="handleOpenAssignPermDialog(scope.row)"
						>
							<i-ep-position/>
							分配权限
						</el-button>
						<el-button
							link
							size="small"
							type="primary"
							@click="handleOpenDialog(scope.row.id)"
						>
							<i-ep-edit/>
							编辑
						</el-button>
						<el-button
							link
							size="small"
							type="danger"
							@click="handleDelete(scope.row.id)"
						>
							<i-ep-delete/>
							删除
						</el-button>
					</template>
				</el-table-column>
			</el-table>

			<pagination
				v-if="total > 0"
				v-model:limit="queryParams.pageSize"
				v-model:page="queryParams.pageNum"
				v-model:total="total"
				@pagination="handleQuery"
			/>
		</el-card>

		<!-- 角色表单弹窗 -->
		<el-dialog
			v-model="dialog.visible"
			:title="dialog.title"
			width="500px"
			@close="handleCloseDialog"
		>
			<el-form
				ref="roleFormRef"
				:model="formData"
				:rules="rules"
				label-width="100px"
			>
				<el-form-item label="角色名称" prop="name">
					<el-input v-model="formData.name" placeholder="请输入角色名称"/>
				</el-form-item>

				<el-form-item label="角色编码" prop="code">
					<el-input v-model="formData.code" placeholder="请输入角色编码"/>
				</el-form-item>

				<el-form-item label="数据权限" prop="dataScope">
					<el-select v-model="formData.dataScope">
						<el-option :key="0" :value="0" label="全部数据"/>
						<el-option :key="1" :value="1" label="部门及子部门数据"/>
						<el-option :key="2" :value="2" label="本部门数据"/>
						<el-option :key="3" :value="3" label="本人数据"/>
					</el-select>
				</el-form-item>

				<el-form-item label="状态" prop="status">
					<el-radio-group v-model="formData.status">
						<el-radio :label="1">正常</el-radio>
						<el-radio :label="0">停用</el-radio>
					</el-radio-group>
				</el-form-item>

				<el-form-item label="排序" prop="sort">
					<el-input-number
						v-model="formData.sort"
						:min="0"
						controls-position="right"
						style="width: 100px"
					/>
				</el-form-item>
			</el-form>

			<template #footer>
				<div class="dialog-footer">
					<el-button type="primary" @click="handleSubmit">确 定</el-button>
					<el-button @click="handleCloseDialog">取 消</el-button>
				</div>
			</template>
		</el-dialog>

		<!-- 分配权限弹窗 -->
		<el-drawer
			v-model="assignPermDialogVisible"
			:title="'【' + checkedRole.name + '】权限分配'"
			size="500"
		>
			<div class="flex-x-between">
				<el-input
					v-model="permKeywords"
					class="w-[200px]"
					clearable
					placeholder="菜单权限名称"
				>
					<template #prefix>
						<i-ep-search/>
					</template>
				</el-input>

				<div class="flex-center">
					<el-button plain size="small" type="primary" @click="togglePermTree"
					>
						<i-ep-switch/>
						{{ isExpanded ? "收缩" : "展开" }}
					</el-button
					>
					<el-checkbox
						v-model="parentChildLinked"
						class="ml-5"
						@change="handleparentChildLinkedChange"
					>父子联动
					</el-checkbox>

					<el-tooltip placement="bottom">
						<template #content>
							如果只需勾选菜单权限，不需要勾选子菜单或者按钮权限，请关闭父子联动
						</template>
						<i-ep-QuestionFilled
							class="ml-1 color-[--el-color-primary] inline-block cursor-pointer"
						/>
					</el-tooltip>
				</div>
			</div>

			<el-tree
				ref="permTreeRef"
				:check-strictly="!parentChildLinked"
				:data="menuPermOptions"
				:default-expand-all="true"
				:filter-node-method="handlePermFilter"
				class="mt-5"
				node-key="value"
				show-checkbox
			>
				<template #default="{ data }">
					{{ data.label }}
				</template>
			</el-tree>

			<template #footer>
				<div class="dialog-footer">
					<el-button type="primary" @click="handleAssignPermSubmit"
					>确 定
					</el-button
					>
					<el-button @click="assignPermDialogVisible = false">取 消</el-button>
				</div>
			</template>
		</el-drawer>
	</div>
</template>

<script lang="ts" setup>
defineOptions({
	name: "Role",
	inheritAttrs: false,
});

import RoleAPI, {RolePageVO, RoleForm, RolePageQuery} from "@api/role";
import MenuAPI from "@api/menu";

const queryFormRef = ref(ElForm);
const roleFormRef = ref(ElForm);
const permTreeRef = ref<InstanceType<typeof ElTree>>();

const loading = ref(false);
const ids = ref<number[]>([]);
const total = ref(0);

const queryParams = reactive<RolePageQuery>({
	pageNum: 1,
	pageSize: 10,
});

// 角色表格数据
const roleList = ref<RolePageVO[]>();
// 菜单权限下拉
const menuPermOptions = ref<OptionType[]>([]);

// 弹窗
const dialog = reactive({
	title: "",
	visible: false,
});
// 角色表单
const formData = reactive<RoleForm>({
	sort: 1,
	status: 1,
	code: "",
	name: "",
});

const rules = reactive({
	name: [{required: true, message: "请输入角色名称", trigger: "blur"}],
	code: [{required: true, message: "请输入角色编码", trigger: "blur"}],
	dataScope: [{required: true, message: "请选择数据权限", trigger: "blur"}],
	status: [{required: true, message: "请选择状态", trigger: "blur"}],
});

// 选中的角色
interface CheckedRole {
	id?: number;
	name?: string;
}

const checkedRole = ref<CheckedRole>({});
const assignPermDialogVisible = ref(false);

const permKeywords = ref("");
const isExpanded = ref(true);

const parentChildLinked = ref(true);

/** 查询 */
function handleQuery() {
	loading.value = true;
	RoleAPI.getPage(queryParams)
		.then((data) => {
			roleList.value = data.list;
			total.value = data.total;
		})
		.finally(() => {
			loading.value = false;
		});
}

/** 重置查询 */
function handleResetQuery() {
	queryFormRef.value.resetFields();
	queryParams.pageNum = 1;
	handleQuery();
}

/** 行复选框选中记录选中ID集合 */
function handleSelectionChange(selection: any) {
	ids.value = selection.map((item: any) => item.id);
}

/** 打开角色弹窗 */
function handleOpenDialog(roleId?: number) {
	dialog.visible = true;
	if (roleId) {
		dialog.title = "修改角色";
		RoleAPI.getFormData(roleId).then((data) => {
			Object.assign(formData, data);
		});
	} else {
		dialog.title = "新增角色";
	}
}

/** 提交角色表单 */
function handleSubmit() {
	roleFormRef.value.validate((valid: any) => {
		if (valid) {
			loading.value = true;
			const roleId = formData.id;
			if (roleId) {
				RoleAPI.update(roleId, formData)
					.then(() => {
						ElMessage.success("修改成功");
						handleCloseDialog();
						handleResetQuery();
					})
					.finally(() => (loading.value = false));
			} else {
				RoleAPI.add(formData)
					.then(() => {
						ElMessage.success("新增成功");
						handleCloseDialog();
						handleResetQuery();
					})
					.finally(() => (loading.value = false));
			}
		}
	});
}

/** 关闭角色弹窗 */
function handleCloseDialog() {
	dialog.visible = false;

	roleFormRef.value.resetFields();
	roleFormRef.value.clearValidate();

	formData.id = undefined;
	formData.sort = 1;
	formData.status = 1;
}

/** 删除角色 */
function handleDelete(roleId?: number) {
	const roleIds = [roleId || ids.value].join(",");
	if (!roleIds) {
		ElMessage.warning("请勾选删除项");
		return;
	}

	ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
		confirmButtonText: "确定",
		cancelButtonText: "取消",
		type: "warning",
	}).then(
		() => {
			loading.value = true;
			RoleAPI.deleteByIds(roleIds)
				.then(() => {
					ElMessage.success("删除成功");
					handleResetQuery();
				})
				.finally(() => (loading.value = false));
		},
		() => {
			ElMessage.info("已取消删除");
		}
	);
}

/** 打开分配菜单权限弹窗 */
async function handleOpenAssignPermDialog(row: RolePageVO) {
	const roleId = row.id;
	if (roleId) {
		assignPermDialogVisible.value = true;
		loading.value = true;

		checkedRole.value.id = roleId;
		checkedRole.value.name = row.name;

		// 获取所有的菜单
		menuPermOptions.value = await MenuAPI.getOptions();

		// 回显角色已拥有的菜单
		RoleAPI.getRoleMenuIds(roleId)
			.then((data) => {
				const checkedMenuIds = data;
				checkedMenuIds.forEach((menuId) =>
					permTreeRef.value!.setChecked(menuId, true, false)
				);
			})
			.finally(() => {
				loading.value = false;
			});
	}
}

/** 分配菜单权限提交 */
function handleAssignPermSubmit() {
	const roleId = checkedRole.value.id;
	if (roleId) {
		const checkedMenuIds: number[] = permTreeRef
			.value!.getCheckedNodes(false, true)
			.map((node: any) => node.value);

		loading.value = true;
		RoleAPI.updateRoleMenus(roleId, checkedMenuIds)
			.then(() => {
				ElMessage.success("分配权限成功");
				assignPermDialogVisible.value = false;
				handleResetQuery();
			})
			.finally(() => {
				loading.value = false;
			});
	}
}

/** 展开/收缩 菜单权限树  */
function togglePermTree() {
	isExpanded.value = !isExpanded.value;
	if (permTreeRef.value) {
		Object.values(permTreeRef.value.store.nodesMap).forEach((node: any) => {
			if (isExpanded.value) {
				node.expand();
			} else {
				node.collapse();
			}
		});
	}
}

/** 权限筛选  */
watch(permKeywords, (val) => {
	permTreeRef.value!.filter(val);
});

function handlePermFilter(
	value: string,
	data: {
		[key: string]: any;
	}
) {
	if (!value) return true;
	return data.label.includes(value);
}

/** 父子菜单节点是否联动 change*/
function handleparentChildLinkedChange(val: any) {
	parentChildLinked.value = val;
}

onMounted(() => {
	handleQuery();
});
</script>
